Skip to content

Fix pin ergonomics borrowck for transient pinned borrows#1

Merged
frank-king merged 1 commit intofrank-king:feature/pin-borrowckfrom
P8L1:fix-pin-ergonomics-transient-pins
Apr 28, 2026
Merged

Fix pin ergonomics borrowck for transient pinned borrows#1
frank-king merged 1 commit intofrank-king:feature/pin-borrowckfrom
P8L1:fix-pin-ergonomics-transient-pins

Conversation

@P8L1
Copy link
Copy Markdown

@P8L1 P8L1 commented Apr 27, 2026

Summary

Fix a false pinned-borrow diagnostic in pin_ergonomics borrow checking for valid T: Unpin coercions involving Pin<&mut T>::as_mut().

The fix distinguishes user-written &pin borrows, which create persistent pinned-place facts, from compiler-generated pinned adjustments and coercions, which should not create long-lived pin facts.

What changed

  • Added mir::PinBorrowKind to distinguish Persistent and Transient pinned borrows.
  • Marked explicit HIR &pin mut place and &pin const place lowering as PinBorrowKind::Persistent.
  • Marked compiler-generated AutoBorrow::Pin lowering as PinBorrowKind::Transient.
  • Changed the Pins dataflow so it records long-lived pin facts only for persistent pinned borrows.
  • Kept transient pinned borrows as ordinary live borrows while they are in scope; they no longer leave behind expired persistent pin facts.
  • Added focused UI coverage for:
    • simple T: Unpin coercion round trips,
    • the Pin<&mut T>::get_mut() followed by as_mut() regression path,
    • projected-place pinning with &pin mut pair.0.

Why

tests/ui/pin-ergonomics/pin-coercion.rs rejected valid T: Unpin coercion code around Pin<&mut T>::as_mut() with:

cannot borrow `x` as mutable because it is pinned

The previous dataflow treated every BorrowKind::Pinned borrow as a long-lived pin fact. That included compiler-generated pinned adjustments used for method receivers and coercions. Those transient adjustments should not make later valid T: Unpin coercion code look like it is mutably borrowing an already pinned place.

This is not a broad Unpin filter: explicit user &pin borrows of Unpin values still create persistent pin facts and remain protected until reassignment.

Tests

Passed:

./x test tests/ui/pin-ergonomics/pin-coercion-unpin-roundtrip.rs --stage 1
./x test tests/ui/pin-ergonomics/pin-coercion-get-mut-then-as-mut.rs --stage 1
./x test tests/ui/pin-ergonomics/pin-coercion.rs --stage 1
./x test tests/ui/pin-ergonomics/borrow.rs --stage 1
./x test tests/ui/pin-ergonomics/borrow-unpin.rs --stage 1
./x test tests/ui/pin-ergonomics/pin-pattern.rs --stage 1
./x test tests/ui/pin-ergonomics/pattern-matching.rs --stage 1
./x test tests/ui/pin-ergonomics/pin-coercion-check.rs --stage 1
./x test tests/ui/pin-ergonomics/borrow-pinned-projection.rs --stage 1
git diff --check
./x fmt --check

Notes for reviewers

The main review point is whether every explicit user &pin path is represented as PinBorrowKind::Persistent, and whether any explicit user pinning path reaches MIR only through AutoBorrow::Pin.

Transient pinned borrows are still treated as normal live borrows; the change is only that they no longer create long-lived expired pin facts in the Pins dataflow.

Related

@frank-king frank-king merged commit 63fbcd8 into frank-king:feature/pin-borrowck Apr 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants